const express = require('express');
const turf = require('@turf/turf');
const cors = require('cors');
const app = express();
const port = 3000;

// 启用 CORS 和 JSON 处理
app.use(cors());
app.use(express.json());
app.use(express.static('.'));

// 1. 距离计算 API
app.post('/api/distance', (req, res) => {
  try {
    const { point1, point2, units } = req.body;
    const from = turf.point(point1);
    const to = turf.point(point2);
    const distance = turf.distance(from, to, { units: units || 'kilometers' });
    
    res.json({
      success: true,
      distance,
      units: units || 'kilometers'
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 2. 点是否在多边形内 API
app.post('/api/pointInPolygon', (req, res) => {
  try {
    const { point, polygon } = req.body;
    const pt = turf.point(point);
    
    // 确保多边形是闭合的（第一个点和最后一个点相同）
    let processedPolygon = [...polygon];
    const firstRing = [...processedPolygon[0]];
    
    // 检查第一个环是否闭合，如果不闭合则闭合它
    if (
      firstRing[0][0] !== firstRing[firstRing.length - 1][0] || 
      firstRing[0][1] !== firstRing[firstRing.length - 1][1]
    ) {
      firstRing.push([...firstRing[0]]);
      processedPolygon[0] = firstRing;
    }
    
    const poly = turf.polygon(processedPolygon);
    const isInside = turf.booleanPointInPolygon(pt, poly);
    
    res.json({
      success: true,
      isInside
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 3. 缓冲区分析 API
app.post('/api/buffer', (req, res) => {
  try {
    const { geojson, radius, units } = req.body;
    const buffered = turf.buffer(geojson, radius, { units: units || 'kilometers' });
    
    res.json({
      success: true,
      bufferedGeojson: buffered
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 4. 最近点查找 API
app.post('/api/nearest', (req, res) => {
  try {
    const { targetPoint, points } = req.body;
    const target = turf.point(targetPoint);
    const pointsCollection = turf.featureCollection(
      points.map(pt => turf.point(pt.coordinates, pt.properties))
    );
    
    const nearest = turf.nearestPoint(target, pointsCollection);
    
    res.json({
      success: true,
      nearest
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 5. 数据简化 API - 用于大数据量优化
app.post('/api/simplify', (req, res) => {
  try {
    const { geojson, tolerance, highQuality } = req.body;
    const simplified = turf.simplify(geojson, { 
      tolerance: tolerance || 0.001, 
      highQuality: highQuality || false 
    });
    
    // 计算简化程度
    const originalPoints = JSON.stringify(geojson).length;
    const simplifiedPoints = JSON.stringify(simplified).length;
    const reductionPercentage = ((originalPoints - simplifiedPoints) / originalPoints * 100).toFixed(2);
    
    res.json({
      success: true,
      simplified,
      stats: {
        originalSize: originalPoints,
        simplifiedSize: simplifiedPoints,
        reduction: `${reductionPercentage}%`
      }
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 6. 地理数据聚合 API
app.post('/api/cluster', (req, res) => {
  try {
    const { points, numberOfClusters } = req.body;
    const pointsCollection = turf.featureCollection(
      points.map(pt => turf.point(pt.coordinates, pt.properties))
    );
    
    const clustered = turf.clustersKmeans(pointsCollection, { numberOfClusters });
    
    // 组织聚类结果
    const clusters = {};
    clustered.features.forEach(pt => {
      const cluster = pt.properties.cluster;
      if (!clusters[cluster]) {
        clusters[cluster] = [];
      }
      clusters[cluster].push(pt);
    });
    
    res.json({
      success: true,
      clusters
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 7. 多边形合并 API
app.post('/api/union', (req, res) => {
  try {
    const { polygons } = req.body;
    if (!polygons || polygons.length < 2) {
      throw new Error('至少需要两个多边形');
    }
    
    // 确保每个多边形都是闭合的（第一个点和最后一个点相同）
    const processedPolygons = polygons.map(polygon => {
      // 确保点数量足够
      if (polygon.length < 4) {
        throw new Error('多边形必须至少有4个点');
      }
      
      // 检查多边形是否闭合，如果不闭合则闭合它
      if (
        polygon[0][0] !== polygon[polygon.length - 1][0] ||
        polygon[0][1] !== polygon[polygon.length - 1][1]
      ) {
        return [...polygon, [...polygon[0]]];
      }
      return polygon;
    });
    
    let unionResult = turf.polygon([processedPolygons[0]]);
    
    // 依次合并多边形
    for (let i = 1; i < processedPolygons.length; i++) {
      const poly = turf.polygon([processedPolygons[i]]);
      unionResult = turf.union(unionResult, poly);
    }
    
    res.json({
      success: true,
      union: unionResult
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 8. 等值线生成 API - 高级空间分析
app.post('/api/isobands', (req, res) => {
  try {
    const { points, breaks, property, cellSize } = req.body;
    
    // 创建带有属性的点集合
    const pointsWithValues = turf.featureCollection(
      points.map(pt => turf.point(pt.coordinates, { [property]: pt.value }))
    );
    
    // 定义研究区域
    const pointCoords = points.map(pt => pt.coordinates);
    const multiPoint = turf.multiPoint(pointCoords);
    const bbox = turf.bbox(multiPoint);
    
    // 插值生成栅格
    const grid = turf.interpolate(pointsWithValues, cellSize || 0.5, {
      property,
      gridType: 'point',
      units: 'kilometers'
    });
    
    // 生成等值线
    const isobands = turf.isobands(grid, breaks, { zProperty: property });
    
    res.json({
      success: true,
      isobands
    });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

// 服务健康检查
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', message: 'Turf.js 空间分析服务运行正常' });
});

app.listen(port, () => {
  console.log(`Turf.js 空间分析服务器运行在 http://localhost:${port}`);
});
